package com.atguigu.aop.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import javax.print.attribute.standard.MediaName;
import java.util.Arrays;

/**
 * @author: 封捷
 * @create-date: 2022/8/27 14:26
 */
// 将切面类加入 IOC 容器
@Component

// 表示当前类是一个切面类
@Aspect
@Slf4j
public class LogAspect {

    /**
     * 环绕通知的通知方法
     * @param joinPoint 包含了环绕通知所需要的各种参数
     * @return 由于外界通过通知方法间接调用目标方法，那么通知方法的返回值就会被外界当作目标方法的返回值
     * @Around 注解表示这个方法是环绕通知，value属性配置切入点表达式
     */
    @Around(value = "execution(public int com.atguigu.aop.api.Calculator.add(int,int))")
    public Object printLog(ProceedingJoinPoint joinPoint) {

        // 声明一个变量，接收目标方法的返回值
        Object targetReturnValue = null;

        // 获取目标方法执行时所需要的参数
        Object[] args = joinPoint.getArgs();

        // Signature 对象：封装了目标方法的签名信息（方法声明时的相关信息）
        Signature signature = joinPoint.getSignature();

        String methodName = signature.getName();

        try {

            // 核心操作前：打印方法开始的日志
            log.info(methodName + " 方法开始了。参数列表：" + Arrays.asList(args));

            // 核心操作：调用目标方法
            targetReturnValue = joinPoint.proceed(args);

            // 核心操作成功：打印方法成功的日志
            log.info(methodName + " 方法成功了。返回值是：" + targetReturnValue);

        } catch (Throwable throwable) {
            // 核心操作失败：打印方法失败的日志
            log.info(methodName + " 方法失败了。异常信息是：" + throwable.getMessage());
        } finally {
            // 核心操作结束：打印方法结束的日志
            log.info(methodName + " 方法结束了。");
        }

        return targetReturnValue;
    }

}
